const socketIO = require('socket.io');
const {getNewMessageCount, getChatList, getMessageList, findUser, addNewMessage, updateNewMessage} = require('../service/userService');

//自定义socket处理程序类
class CustomSocket {
    constructor(server) {
        this.io = socketIO(server, {
            allowEIO3: true,
            cors: {//跨域
                origin: ['http://43.138.133.11:3003'],
                methods: ['GET', 'POST'],
                credentials: true
            }
        });
        //用户对象
        this.userListObject = {};
        this.handleEvent();
    }

    //处理事件
    handleEvent() {
        //监听客户端连接
        this.io.on('connection', async (socket) => {
            let currentUserId = 0;//当前用户id
            //监听用户登录
            socket.on('login', async (data) => {
                currentUserId = data.id;
                this.addToUserListObject(data.id, socket);
            });
            //监听用户登出
            socket.on('logout', () => {
                this.removeFromUserListObject(currentUserId, socket);
            });
            //监听获取新消息数事件
            socket.on('getNewMessageCount', async () => {
                //获取新消息数
                await CustomSocket.getNewMessageCount(currentUserId, socket);
            });
            //监听获取聊天列表事件
            socket.on('getChatList', async () => {
                await CustomSocket.getChatList(currentUserId, socket);
            });
            //获取与指定用户的聊天记录
            socket.on('getMessageList', async (userId) => {
                socket['isChat'] = true;//是否在聊天框
                const data = await getMessageList(currentUserId, userId, 0);
                socket.emit('messageList', data);

                //通知用户更新新消息数和聊天列表
                await CustomSocket.getNewMessageCount(currentUserId, socket);
                await CustomSocket.getChatList(currentUserId, socket);
                //通知对方我已读消息
                await this.messageIsRead(currentUserId, userId);
            });
            //获取下一段聊天记录
            socket.on('getNextMessageList', async (userId, offset) => {
                const data = await getMessageList(currentUserId, userId, offset);
                socket.emit('nextMessageList', data);
            });
            //监听获取当前用户信息
            socket.on('getUserInfo', async (userId) => {
                const data = await findUser({id: userId});
                socket.emit('userInfo', data);
            });
            //发送消息
            socket.on('sendMessage', async (data) => {
                data['fromUserId'] = currentUserId;
                const result = await addNewMessage(data);
                //socket.emit('successAddMessage', result);
                //通知用户更新聊天列表
                //await CustomSocket.getChatList(currentUserId, socket);
                await this.sendToOther(currentUserId, socket, result);
                //发送消息给对方
                await this.sendMessageToOther(currentUserId, data['toUserId'], result.data);
            });
            //通知对方成功接收消息
            socket.on('notifyAcceptSuccess', async (data) => {
                //更新消息为已读
                await updateNewMessage({fromUserId: data['toUserId'], toUserId: currentUserId});
                //更新新消息数和聊天列表
                await CustomSocket.getNewMessageCount(currentUserId, socket);
                await CustomSocket.getChatList(currentUserId, socket);
                //通知对方已接收消息
                await this.messageIsRead(currentUserId, data['toUserId']);
            });
            //监听用户是否进入聊天
            socket.on('isChat', async () => {
                socket['isChat'] = true;//是否在聊天框
            });
            //监听用户是否离开聊天框
            socket.on('leaveChat', async () => {
                socket['isChat'] = false;//是否在聊天框
            });
            //监听客户端断开连接
            socket.on('disconnect', () => {
                this.removeFromUserListObject(currentUserId, socket);
            });
        });
    }

    //发送消息给同一浏览器的不同标签页
    async sendToOther(id, socket, data) {
        const list = this.userListObject[id];
        //如果对方在线则发送
        if (list && list.length > 0) {
            for (let i = 0; i < list.length; i++) {
                list[i].emit('successAddMessage', data);
                //通知用户更新聊天列表
                await CustomSocket.getChatList(id, list[i]);
            }
        }
    }

    //发送消息给对方
    async sendMessageToOther(fromUserId, toUserId, message) {
        const list = this.userListObject[toUserId];
        //如果对方在线则发送
        if (list && list.length > 0) {
            for (let i = 0; i < list.length; i++) {
                if (list[i]['isChat']) {
                    list[i].emit('acceptMessage', message);
                } else {
                    await CustomSocket.getNewMessageCount(toUserId, list[i]);
                    await CustomSocket.getChatList(toUserId, list[i]);
                }
                list[i].emit('newMessageSound');
            }
        }
    }

    //通知对方已接收消息
    async messageIsRead(fromUserId, toUserId) {
        const list = this.userListObject[toUserId];
        //如果对方在线则发送
        if (list && list.length > 0) {
            for (let i = 0; i < list.length; i++) {
                list[i].emit('messageIsRead', {fromUserId, toUserId});
            }
        }
    }

    //添加到用户对象
    addToUserListObject(id, socket) {
        if (this.userListObject[id]) {
            if (!this.userListObject[id].includes(socket)) {
                this.userListObject[id].push(socket);
            }
        } else {
            this.userListObject[id] = [socket];
        }
    }

    //从用户对象移除
    removeFromUserListObject(id, socket) {
        if (this.userListObject[id]) {
            let index = this.userListObject[id].indexOf(socket);
            if (index > -1) {
                this.userListObject[id].splice(index, 1);
            }
        }
    }

    //返回未读消息数
    static async getNewMessageCount(id, socket) {
        const count = await getNewMessageCount(id);
        socket.emit('newMessageCount', count);
    }

    //获取当前用户聊天列表
    static async getChatList(id, socket) {
        const data = await getChatList({id});
        socket.emit('chatList', data.data.list);
    }

    //判断用户是否退出登录
    async logout(id, socket) {

    }
}

module.exports = CustomSocket;